package internal

import (
	"context"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"

	pkglogger "baseService/internal/pkg/logger"
)

// ShutdownManager 优雅关闭管理器
type ShutdownManager struct {
	logger    pkglogger.Logger
	callbacks []func(ctx context.Context) error
	timeout   time.Duration
	mu        sync.Mutex
}

// NewShutdownManager 创建关闭管理器
func NewShutdownManager(logger pkglogger.Logger, timeout time.Duration) *ShutdownManager {
	if timeout <= 0 {
		timeout = 30 * time.Second // 默认30秒超时
	}

	return &ShutdownManager{
		logger:    logger,
		callbacks: make([]func(ctx context.Context) error, 0),
		timeout:   timeout,
	}
}

// RegisterCallback 注册关闭回调函数
func (sm *ShutdownManager) RegisterCallback(callback func(ctx context.Context) error) {
	sm.mu.Lock()
	defer sm.mu.Unlock()
	sm.callbacks = append(sm.callbacks, callback)
}

// WaitForShutdown 等待关闭信号并执行优雅关闭
func (sm *ShutdownManager) WaitForShutdown() {
	// 创建信号通道
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)

	// 等待信号
	sig := <-quit
	sm.logger.Infof("接收到关闭信号，开始优雅关闭 - signal: %s, timeout: %v",
		sig.String(), sm.timeout)

	// 创建关闭上下文
	ctx, cancel := context.WithTimeout(context.Background(), sm.timeout)
	defer cancel()

	// 执行所有关闭回调
	sm.executeCallbacks(ctx)

	sm.logger.Info("优雅关闭完成")
}

// executeCallbacks 执行所有关闭回调
func (sm *ShutdownManager) executeCallbacks(ctx context.Context) {
	sm.mu.Lock()
	callbacks := make([]func(ctx context.Context) error, len(sm.callbacks))
	copy(callbacks, sm.callbacks)
	sm.mu.Unlock()

	// 并发执行所有回调
	wg := sync.WaitGroup{}
	errorChan := make(chan error, len(callbacks))

	for i, callback := range callbacks {
		wg.Add(1)
		go func(index int, cb func(ctx context.Context) error) {
			defer wg.Done()

			sm.logger.Debugf("执行关闭回调 - callback_index: %d", index)

			if err := cb(ctx); err != nil {
				sm.logger.Errorf("关闭回调执行失败 - callback_index: %d, error: %v", index, err)
				errorChan <- err
			} else {
				sm.logger.Debugf("关闭回调执行成功 - callback_index: %d", index)
			}
		}(i, callback)
	}

	// 等待所有回调完成
	done := make(chan struct{})
	go func() {
		wg.Wait()
		close(done)
	}()

	// 等待完成或超时
	select {
	case <-done:
		sm.logger.Info("所有关闭回调执行完成")
	case <-ctx.Done():
		sm.logger.Warn("关闭操作超时，强制退出")
	}

	// 收集错误
	close(errorChan)
	errorCount := 0
	for err := range errorChan {
		if err != nil {
			errorCount++
		}
	}

	if errorCount > 0 {
		sm.logger.Warnf("关闭过程中出现错误 - error_count: %d", errorCount)
	}
}
